home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Snippets / Stuart's Tech Notes / Debugging 'orphan' code < prev    next >
Text File  |  1995-09-17  |  3KB  |  80 lines

  1. // Debugging 'orphan' code
  2. // (C) 1995 Stuart Cheshire <cheshire@cs.stanford.edu>
  3.  
  4. Did you get stuck trying to write your first trap-patching INIT?
  5. Did you put in DebugStr calls which just printed garbage in MacsBug?
  6. Well, I did, and it made the legendary Macintosh learning curve even
  7. steeper.
  8.  
  9. Applications on the Mac usually have register A5 set up to point to
  10. their global variables. Standalone code resources often use register
  11. A4 for a similar purpose. 'Orphan' code is code that doesn't have
  12. either A4 or A5 set up to point at it's globals. Trap patches,
  13. completion routines and AppleTalk socket listeners are all 'orphan'
  14. code that cannot access their global variables until they manually
  15. set up the correct base address value in the register.
  16.  
  17. The problem is that even innocent-looking things such as strings for
  18. DebugStr calls count as global variables and require the base register
  19. to be set up correctly. Even in a standalone code resource, Think C
  20. references all static data as an offset from a base register. Why
  21. it doesn't use PC-relative references is a mystery. (A PC-relative
  22. reference is where the compiler uses instructions that say things
  23. like "the address 112 bytes before the address of this instruction
  24. in memory".) No matter where a standalone code resource is loaded in
  25. memory, a PC-relative reference will always be correct. Think C uses
  26. references relative to register A4, which means that you have to make
  27. sure register A4 is set up before you do anything which depends on it.
  28.  
  29. The catch-22 for learning programmers trying to debug their code to find
  30. out why register A4 is not set up correctly is that in Think C the DebugStr
  31. call doesn't work unless you already have register A4 set up correctly.
  32.  
  33. Even for experienced programmers, sometimes you want to be able to put
  34. in a DebugStr breakpoint without having to go to all the effort of
  35. setting up A4 and then restoring it afterwards. That's why I wrote the
  36. FixAddress routine:
  37.  
  38. // Fixes an (erroneous) A4 relative address on top of stack
  39. static void FixAddress()        
  40.     {
  41.     asm    {    movem.l    d0/a4, -(sp)    ; save registers
  42.             move.l    a4, d0
  43.             sub.l    d0, 12(sp)        ; subtract incorrect base from argument
  44.             jsr        __GetA4
  45.             move.l    (a4), d0        ; get correct a4 value
  46.             add.l    d0, 12(sp)        ; add correct base address to argument
  47.             movem.l    (sp)+, d0/a4
  48.         }
  49.     }
  50.  
  51. The way you use it is like this:
  52.  
  53.         pea        "\pThis is a Breakpoint"
  54.         bsr        FixAddress
  55.         _DebugStr
  56.  
  57. The pea instruction pushes the address of the string on the stack, as a
  58. relative offset from the address in register A4 (which may be incorrect).
  59. The call to FixAddress then repairs this address, if it was wrong, so
  60. that the following DebugStr call will work correctly.
  61.  
  62. This assumes that __GetA4 is defined as:
  63. static void __GetA4(void)
  64.     {
  65.     asm {    bsr.s    @1
  66.             dc.l    0            ; store A4 here
  67.         @1    move.l    (sp)+, a4    ; A4 contains the address of my A4 value
  68.         }
  69.     }
  70.  
  71. If the __GetA4 routine your code uses returns the address in a different
  72. register (eg. a1), then you must change FixAddress to use that register,
  73. eg.
  74.             move.l    (a1), d0        ; get correct a4 value
  75.  
  76. Obviously for application code, you should change this to use register A5
  77. instead of A4.
  78.  
  79. Share and enjoy.
  80.